import { BrowserWindow, remote, ipcRenderer } from "electron";
import { IAppContainerOptions, IApp, IAppParams, IAppQuery, IAppView } from "@anyshare/common/lib/stores";
import { BlankWindow } from "./BlankWindow";
import qs from "query-string";
import * as pathToRegexp from "path-to-regexp";
import path from "path";
import { isLinux } from "@anyshare/common/lib/utils/platform";
export interface IAppWindowOptions {
    app: IApp;
    view: IAppView<any>;
    params: IAppParams;
    query: IAppQuery;
    containerOptions?: IAppContainerOptions;
    fromBlankWindow?: BlankWindow;
}

export class AppWindow {
    private readonly _win: BrowserWindow;
    private readonly _id: number;
    private _isReady: boolean;
    private readonly whenReadyCallbacks: {
        (window: AppWindow): void;
    }[];

    public app: IApp;
    public view: IAppView<any>;
    public params: IAppParams;
    public query: IAppQuery;
    public url: string;

    constructor({ app, view, params, query, fromBlankWindow, containerOptions }: IAppWindowOptions) {
        this.app = app;
        this.view = view;
        this.params = params;
        this.query = query;

        this._isReady = false;

        this.url = qs.stringifyUrl(
            {
                url: pathToRegexp.compile(`${app.name}${view.path}`)(params),
                query,
            },
            { arrayFormat: "comma" }
        );

        if (fromBlankWindow) {
            this._win = fromBlankWindow.win;
            this._id = fromBlankWindow.win.id;
            fromBlankWindow.sendWhenReady("redirect", this.url);
        } else {
            this._win = new remote.BrowserWindow({
                frame: false,
                show: false,
                icon: isLinux ? path.resolve(remote.app.getAppPath(), "./resources/common/icon.png") : undefined,
                webPreferences: {
                    devTools: true,
                    nodeIntegration: true,
                    nodeIntegrationInWorker: true,
                    webSecurity: false,
                    enableRemoteModule: true,
                },
            });
            this._id = this._win.id;
            this._win.loadURL(
                `${window.location.protocol}//${window.location.host}${window.location.pathname}#/anyshare/${this.url}`
            );
        }

        const {
            width,
            height,
            center,
            x,
            y,
            parentContainerId,
            maximizable = true,
            minimizable = true,
            closable = true,
            fullscreenable = false,
            movable = true,
            resizable = true,
            minWidth,
            minHeight,
            skipTaskbar,
        } = {
            ...view.defaults?.containerOptions,
            ...containerOptions,
        };

        this._win.setMaximizable(maximizable);
        this._win.setMinimizable(minimizable);
        this._win.setClosable(closable);
        this._win.setFullScreenable(fullscreenable);
        this._win.setMovable(movable);
        this._win.setSkipTaskbar(skipTaskbar || false);

        if (minWidth && minHeight) {
            this._win.setMinimumSize(minWidth, minHeight);
        }

        if (width && height) {
            this._win.setSize(width, height);
        }
        this._win.setResizable(resizable);

        if (center || x === undefined || y === undefined) {
            this._win.center();
        } else if (typeof x === "number" && typeof y === "number") {
            this._win.setPosition(x, y);
        }

        if (parentContainerId && typeof this._win.setParentWindow === "function") {
            this._win.setParentWindow(remote.BrowserWindow.fromId(parentContainerId));
        }

        this.whenReadyCallbacks = [];

        this.ready().then(() => {
            if (!isLinux) {
                setTimeout(() => {
                    if (app.name !== "syncdetails") {
                        this._win.show();

                        // 确保窗口显示出来的时候位于顶层
                        this._win.setAlwaysOnTop(true);
                        this._win.setAlwaysOnTop(false);
                    }
                }, 200);
            } else {
                if (app.name !== "syncdetails") {
                    this._win.show();
                }
            }
            if (containerOptions?.replyChannel && containerOptions.openerId) {
                ipcRenderer.sendTo(containerOptions.openerId, containerOptions.replyChannel, { id: this._win.id });
            }
        });
    }

    public get id() {
        return this._id;
    }

    public get win() {
        return this._win;
    }

    public get isReady() {
        return this._isReady;
    }

    public ready(): Promise<AppWindow> {
        return new Promise<AppWindow>((resolve) => {
            if (this.isReady) {
                return resolve(this);
            }
            this.whenReadyCallbacks.push(resolve);
        });
    }

    public setReady() {
        this._isReady = true;
        while (this.whenReadyCallbacks.length) {
            this.whenReadyCallbacks.pop()!(this);
        }
    }

    public send(channel: string, ...args: any[]) {
        if (this._win && !this._win.isDestroyed()) {
            this._win.webContents.send(channel, ...args);
        }
    }

    public sendWhenReady(channel: string, ...args: any[]) {
        if (this.isReady) {
            this.send(channel, ...args);
        } else {
            this.ready().then(() => this.send(channel, ...args));
        }
    }
}
